#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
SQL语法高亮器模块
为SQL编辑器提供语法高亮功能
"""

from PySide6.QtCore import QRegularExpression, Qt
from PySide6.QtGui import QColor, QTextCharFormat, QFont, QSyntaxHighlighter
from PySide6.QtGui import QTextCharFormat, QTextBlockUserData, QTextCursor

from config.settings import settings


class SQLBlockData(QTextBlockUserData):
    """SQL代码块用户数据，用于存储代码块的附加信息"""
    
    def __init__(self):
        """初始化SQL代码块数据"""
        super().__init__()
        self.folded = False  # 是否折叠
        self.errors = []  # 错误信息列表


class SQLHighlighter(QSyntaxHighlighter):
    """SQL语法高亮器类"""
    
    def __init__(self, parent=None):
        """初始化SQL语法高亮器
        
        Args:
            parent: 父对象
        """
        super().__init__(parent)
        
        self._highlighting_rules = []
        
        # SQL关键字
        keywords = [
            'SELECT', 'FROM', 'WHERE', 'GROUP', 'BY', 'HAVING', 'ORDER',
            'INSERT', 'UPDATE', 'DELETE', 'DROP', 'CREATE', 'ALTER', 'TABLE',
            'INDEX', 'VIEW', 'JOIN', 'INNER', 'LEFT', 'RIGHT', 'OUTER', 'FULL',
            'CROSS', 'NATURAL', 'ON', 'USING', 'AND', 'OR', 'NOT', 'IS', 'NULL',
            'LIKE', 'IN', 'EXISTS', 'ALL', 'ANY', 'SOME', 'UNION', 'INTERSECT',
            'EXCEPT', 'CASE', 'WHEN', 'THEN', 'ELSE', 'END', 'DISTINCT', 'AS',
            'WITH', 'RECURSIVE', 'OVER', 'PARTITION', 'BETWEEN', 'LIMIT', 'OFFSET',
            'ASC', 'DESC', 'VALUES', 'SET', 'INTO', 'DEFAULT', 'RETURNING',
            'PRIMARY', 'KEY', 'CONSTRAINT', 'DEFAULT', 'UNIQUE', 'CHECK',
            'REFERENCES', 'CASCADE', 'RESTRICT', 'GRANT', 'REVOKE',
            'TEMPORARY', 'TEMP', 'TRIGGER', 'BEFORE', 'AFTER', 'INSTEAD',
            'OF', 'EACH', 'ROW', 'EXECUTE', 'LANGUAGE', 'FUNCTION', 'RETURNS',
            'RETURN', 'DECLARE', 'FETCH', 'CURSOR', 'EXPLAIN'
        ]
        
        # SQL函数
        functions = [
            'COUNT', 'SUM', 'AVG', 'MIN', 'MAX', 'COALESCE', 'NULLIF', 'CAST',
            'EXTRACT', 'SUBSTRING', 'SUBSTR', 'TRIM', 'UPPER', 'LOWER', 'DATE_TRUNC',
            'DATE_PART', 'TO_CHAR', 'TO_DATE', 'LENGTH', 'ROUND', 'CEIL', 'FLOOR', 'ABS',
            'CONCAT', 'REPLACE', 'REGEXP_MATCHES', 'LAG', 'LEAD', 'RANK',
            'ROW_NUMBER', 'DENSE_RANK', 'ARRAY_AGG', 'STRING_AGG', 'JSON_AGG',
            'FIRST', 'LAST', 'NTH_VALUE', 'NTILE', 'VARIANCE', 'STDDEV',
            'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', 'NOW', 'EXTRACT', 'DATE_PART',
            'DATE_ADD', 'DATE_SUB', 'DATEDIFF', 'DATEADD', 'CONVERT', 'TRY_CAST',
            'FORMAT', 'LEFT', 'RIGHT', 'CHARINDEX', 'POSITION', 'INSTR',
            'YEAR', 'MONTH', 'DAY', 'HOUR', 'MINUTE', 'SECOND',
            'POWER', 'SQRT', 'LN', 'LOG', 'LOG10', 'EXP', 'MOD', 'RANDOM',
            'STRING_SPLIT', 'ARRAY_CONTAINS', 'JSON_EXTRACT', 'REGEXP_REPLACE'
        ]
        
        # SQL数据类型
        types = [
            'INTEGER', 'INT', 'SMALLINT', 'BIGINT', 'TINYINT', 'VARCHAR', 'CHAR',
            'TEXT', 'BOOLEAN', 'BOOL', 'REAL', 'FLOAT', 'DOUBLE', 'DECIMAL', 'NUMERIC',
            'DATE', 'TIME', 'TIMESTAMP', 'INTERVAL', 'BLOB', 'JSON', 'UUID', 'ARRAY',
            'ENUM', 'GEOMETRY', 'POINT', 'LINESTRING', 'POLYGON'
        ]
        
        # DuckDB特有的函数
        duckdb_functions = [
            'READ_CSV', 'READ_CSV_AUTO', 'READ_PARQUET', 'READ_JSON',
            'CURRENT_SCHEMA', 'PRAGMA_TABLE_INFO', 'LIST', 'LIST_TABLES',
            'DESCRIBE', 'EXPLAIN', 'GENERATE_SERIES', 'UNNEST', 'STRUCT_PACK',
            'STRUCT_EXTRACT', 'LIST_EXTRACT', 'LIST_CONCAT', 'LIST_APPEND',
            'MAP', 'MAP_EXTRACT', 'STRING_SPLIT_REGEX', 'REGEX_REPLACE',
            'FROM_JSON', 'TO_JSON', 'PARQUET_SCAN', 'JSON_EXTRACT_STRING',
            'JSON_TRANSFORM', 'ARRAY_SLICE', 'RANGE', 'IFNULL'
        ]
        
        # 保存关键字列表
        self.keywords = keywords
        self.functions = functions
        self.duckdb_functions = duckdb_functions
        self.types = types
        
        # 定义多行注释的正则表达式
        self.comment_start_expression = QRegularExpression(r'/\*')
        self.comment_end_expression = QRegularExpression(r'\*/')
        
        # 应用默认主题
        self.apply_theme()
        
    def apply_theme(self, theme_name=None):
        """应用默认主题配置"""
        # 使用硬编码的默认颜色配置
        # 设置各种语法元素的格式
        # 关键字
        keyword_format = QTextCharFormat()
        keyword_format.setForeground(QColor("#0000FF"))  # 蓝色
        keyword_format.setFontWeight(QFont.Bold)
        
        # 函数
        function_format = QTextCharFormat()
        function_format.setForeground(QColor("#795E26"))  # 棕色
        
        # 字符串
        string_format = QTextCharFormat()
        string_format.setForeground(QColor("#A31515"))  # 深红色
        
        # 数字
        number_format = QTextCharFormat()
        number_format.setForeground(QColor("#098658"))  # 绿色
        
        # 注释
        comment_format = QTextCharFormat()
        comment_format.setForeground(QColor("#008000"))  # 绿色
        comment_format.setFontItalic(True)
        
        # 操作符
        operator_format = QTextCharFormat()
        operator_format.setForeground(QColor("#000000"))  # 黑色
        operator_format.setFontWeight(QFont.Bold)
        
        # 表名和字段名
        identifier_format = QTextCharFormat()
        identifier_format.setForeground(QColor("#001080"))  # 深蓝色
        
        # 数据类型
        type_format = QTextCharFormat()
        type_format.setForeground(QColor("#267F99"))  # 青色
        type_format.setFontWeight(QFont.Bold)
        
        # 括号和分隔符
        delimiter_format = QTextCharFormat()
        delimiter_format.setForeground(QColor("#000000"))  # 黑色
        
        # 更新格式规则
        self._highlighting_rules = [
            # 关键字
            (QRegularExpression("\\b(" + "|".join(self.keywords) + ")\\b", QRegularExpression.CaseInsensitiveOption), 
             keyword_format),
            
            # 函数
            (QRegularExpression("\\b(" + "|".join(self.functions) + ")\\s*\\(", QRegularExpression.CaseInsensitiveOption), 
             function_format),
            
            # 单引号字符串
            (QRegularExpression("'[^']*'"), string_format),
            
            # 双引号字符串
            (QRegularExpression("\"[^\"]*\""), string_format),
            
            # 数字
            (QRegularExpression("\\b[0-9]+\\b"), number_format),
            
            # 单行注释
            (QRegularExpression("--[^\n]*"), comment_format),
            
            # 操作符
            (QRegularExpression("[\\+\\-\\*\\/\\%\\=\\<\\>\\!\\&\\|\\^\\~]+"), operator_format),
            
            # 表名和字段名
            (QRegularExpression("\\b[a-zA-Z_][a-zA-Z0-9_]*\\b"), identifier_format),
            
            # 数据类型
            (QRegularExpression("\\b(" + "|".join(self.types) + ")\\b", QRegularExpression.CaseInsensitiveOption), 
             type_format),
            
            # 括号和分隔符
            (QRegularExpression("[\\(\\)\\[\\]\\{\\}\\,\\;]"), delimiter_format),
        ]
        
        # 保存多行注释的格式
        self.multiline_comment_format = comment_format
        
        # 触发重新高亮
        self.rehighlight()
        
    def highlightBlock(self, text):
        """高亮文本块
        
        Args:
            text: 要高亮的文本
        """
        # 检查文本是否为空
        if not text:
            return
        
        # 清除任何之前的格式
        self.setFormat(0, len(text), QTextCharFormat())
            
        # 应用语法高亮规则
        for pattern, format in self._highlighting_rules:
            match_iterator = pattern.globalMatch(text)
            while match_iterator.hasNext():
                match = match_iterator.next()
                if match.hasMatch():  # 确保匹配成功
                    start = match.capturedStart()
                    length = match.capturedLength()
                    # 确保高亮区域有效
                    if start >= 0 and length > 0 and start + length <= len(text):
                        self.setFormat(start, length, format)
                
        # 处理多行注释
        self.setCurrentBlockState(0)
        
        start_index = 0
        if self.previousBlockState() != 1:
            match = self.comment_start_expression.match(text)
            start_index = match.capturedStart() if match.hasMatch() else -1
            
        while start_index >= 0:
            match = self.comment_end_expression.match(text, start_index)
            end_index = match.capturedStart() if match.hasMatch() else -1
            comment_length = 0
            
            if end_index == -1:
                self.setCurrentBlockState(1)
                comment_length = len(text) - start_index
            else:
                comment_length = end_index - start_index + match.capturedLength()
                
            self.setFormat(start_index, comment_length, self.multiline_comment_format)
            
            next_match = self.comment_start_expression.match(text, start_index + comment_length)
            start_index = next_match.capturedStart() if next_match.hasMatch() else -1
            
        # 确保每个块都有块数据
        block_data = self.currentBlockUserData()
        if not isinstance(block_data, SQLBlockData):
            block_data = SQLBlockData()
            self.setCurrentBlockUserData(block_data)


class SQLErrorHighlighter:
    """SQL错误高亮器类"""
    
    def __init__(self, document):
        """初始化SQL错误高亮器
        
        Args:
            document: 文本文档
        """
        self.document = document
        self.error_format = QTextCharFormat()
        self.error_format.setUnderlineStyle(QTextCharFormat.WaveUnderline)
        self.error_format.setUnderlineColor(QColor("#FF6464"))
        self.error_format.setToolTip("语法错误")
        self.errors = []
        
    def clear_errors(self):
        """清除所有错误标记"""
        cursor = QTextCursor(self.document)
        cursor.movePosition(QTextCursor.Start)
        cursor.movePosition(QTextCursor.End, QTextCursor.KeepAnchor)
        cursor.setCharFormat(QTextCharFormat())  # 清除格式
        self.errors = []
        
    def mark_error(self, start, length, error_message=None):
        """标记错误
        
        Args:
            start: 起始位置
            length: 长度
            error_message: 错误消息
        """
        # 存储错误信息
        self.errors.append({
            'start': start,
            'length': length,
            'message': error_message
        })
        
        # 应用错误格式
        cursor = QTextCursor(self.document)
        cursor.setPosition(start)
        cursor.movePosition(QTextCursor.Right, QTextCursor.KeepAnchor, length)
        
        error_format = QTextCharFormat(self.error_format)
        if error_message:
            error_format.setToolTip(error_message)
            
        cursor.mergeCharFormat(error_format)
        
    def mark_error_at_position(self, line, column, length, error_message=None):
        """在指定位置标记错误
        
        Args:
            line: 行号 (0-based)
            column: 列号 (0-based)
            length: 长度
            error_message: 错误消息
        """
        # 获取指定位置
        block = self.document.findBlockByNumber(line)
        if not block.isValid():
            return
            
        position = block.position() + column
        
        # 标记错误
        self.mark_error(position, length, error_message)
        
    def get_error_at_position(self, position):
        """获取指定位置的错误信息
        
        Args:
            position: 文档中的位置
            
        Returns:
            错误信息或None
        """
        for error in self.errors:
            if error['start'] <= position < error['start'] + error['length']:
                return error
        return None 